<!DOCTYPE>
<html>
  <head>
    <meta charset="utf-8">
    <title>task 07</title>
    <style type="text/css">
      * {
        margin: 0;
        padding: 0;
      }
      div {
        padding: 20px 10px;
        border: 1px solid #000;
        float: left;
        width: 45%;
        margin: 0 2.5%;
        box-sizing: border-box;
      }
      div.active {
        background: red;
      }
      div.active div {
        background: #fff;
      }
      .center {
        width: 500px;
        margin: 0 auto;
        margin-top: 20px;
        float: none;
        padding: 0;
        overflow: hidden;
      }
      .center button {
        width: 100px;
        height: 50px;
        float: left;
        margin: 20px auto;
        margin-left: 50px;
      }
      .foot {
        position: absolute;
        left: 50%;
        top: 20%;
        margin: 0;
        margin-left: -300px;
        width: 600px;
        overflow: hidden;
      }
    </style>
  </head>
<body>
<!-- 遍历按钮 -->
<div class="center">
  <button id="preorder">前序遍历</button>
  <button id="inorder">中序遍历</button>
  <button id="postorder">后序遍历</button>
</div>
<!-- 二叉树页面结构 -->
<div id="bt" class="foot">
  <div>
    <div>
      <div></div>
      <div></div>
    </div>
    <div>
      <div></div>
      <div></div>
    </div>
  </div>
  <div>
    <div>
      <div></div>
      <div></div>
    </div>
    <div>
      <div></div>
      <div></div>
    </div>
  </div>
</div>

<script type="text/javascript">
  /**
   * 节点类
   * data: 存储二叉树信息的DOM根节点
   * left: 左树
   * right: 右树
   */
  function node(data, left, right, parent) {
    // 初始化属性
    this.data = data;
    this.left = left;
    this.right = right;
    this.parent = parent;
  }

  /** 树类
   *  data: DOM值
   */
  function tree(data) {
    // 初始化根节点
    this.root = new node(data, null, null, null);
    this.animation = animation;
    // 通过数据来填充返回值
    init(this.root, data);
  }

  /** preorder 先序遍历
   *  rootNode: 当前节点
   */ 
  function preOrder(rootNode, resultArr) {
    // 如果为空,则返回
    if(!rootNode.data) {return;}
    resultArr.push(rootNode.data);
    preOrder(rootNode.left, resultArr);
    preOrder(rootNode.right, resultArr);
  }


  /** inorder 中序遍历
   *  rootNode: 当前节点
   */ 
  function inOrder(rootNode, resultArr) {
    // 如果为空,则返回
    if(!rootNode.data) {return;}
    inOrder(rootNode.left, resultArr);
    resultArr.push(rootNode.data);
    inOrder(rootNode.right, resultArr);
  }

  /** postorder 后序遍历
   *  rootNode: 当前节点
   */ 
  function postOrder(rootNode, resultArr) {
    // 如果为空,则返回
    if(!rootNode.data) {return;}
    postOrder(rootNode.left, resultArr);
    postOrder(rootNode.right, resultArr);
    resultArr.push(rootNode.data);
  }

  /** 利用DOM结构初始化树的值 
   *  targetNode: 根节点
   *  data: DOM值
   */
  function init(targetNode, data) {
    // 传进来的数据非节点
    if(!data) {
      return null;
    }
    targetNode.data = data;
    var dataArr = data.children;
    targetNode.left = new node(dataArr[0], null, null, targetNode);
    init(targetNode.left, dataArr[0]);
    targetNode.right = new node(dataArr[1], null, null, targetNode);
    init(targetNode.right, dataArr[1]);

  };

  /** 动画效果 
   *  domArr: 遍历后的节点数组
   *  interval: 动画每帧间隔时间
   */
  function animation(domArr, interval) {
    var slip = 0;
    interval = interval || 500;
    // 插入动画
    for(var i = 0; i < domArr.length; i ++) {
      slip += interval;
      // 利用闭包进行循环
      (function(i, slip) {
        setTimeout(function() {
          if(i >= 1) {
            domArr[i - 1].className = domArr[i - 1].className.replace("active", "");
          }
          domArr[i].className += " active";
        }, slip)
      })(i, slip);
      // 动画结束
      if(i == (domArr.length - 1)) {
        slip += interval;
        (function(i, slip) {
          setTimeout(function() {
            domArr[i].className = domArr[i].className.replace("active", "");
            // 解除阻止
            var btnList = document.getElementsByTagName("button");
            for(var j = 0; j < btnList.length; j ++) {
              btnList[j].removeAttribute("disabled");
            }
          }, slip)
        })(i, slip);
      }
    }
  
  };

  /** 遍历方法
   *  type: 遍历类型
   *  前序遍历
   *  中序遍历
   *  后序遍历
   */
  tree.prototype.traverse = function(type) {
    var rootNode = this.root,
      resultArr = [];

    // 在某种遍历进行中,阻止其他遍历
    var btnList = document.getElementsByTagName("button");
    for(var i = 0; i < btnList.length; i ++) {
      btnList[i].setAttribute("disabled", "true");
    }

    // 根据类型遍历
    switch(type) {
      case "preorder":
        preOrder(rootNode, resultArr);
        break;
      case "inorder":
        // 中序遍历
        inOrder(rootNode, resultArr);
        break;
      case "postorder":
        postOrder(rootNode, resultArr);
        break;
    }

    this.animation(resultArr, 500);
    // 返回排序遍历后的节点数组. 
    return resultArr;

  };

  // 页面事件委托
  document.addEventListener("click", function(evt) {
    var targetID = evt.target.id,
      target = document.getElementById("bt"),
      pageTree = new tree(target);
    
    if(targetID != "inorder" && targetID != "postorder" && targetID != "preorder") {
      return;
    }

    // 遍历树节点  
    pageTree.traverse(targetID);

  });
</script>
</body>
</html>